package com.jl.annotation.aspet;

import com.jl.JLRedissonTemplate;
import com.jl.annotation.JLRedisson;
import com.jl.error.JLRedissonError;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class JLRedisAspet {

    @Autowired
    private JLRedissonTemplate jlRedissonTemplate;

    /**
     * 分布式锁
     *
     * @param joinPoint
     * @param jlRedisson
     * @return
     * @throws Throwable
     */
    @Around("@annotation(jlRedisson)")
    public Object jLRedisson(ProceedingJoinPoint joinPoint, JLRedisson jlRedisson) throws Throwable {
        Object[] args = joinPoint.getArgs();
        Object result;
        String value = jlRedisson.value();
        RLock lock = jlRedissonTemplate.getLock(value);
        try {
            boolean fal;
            int loseTime = jlRedisson.loseTime();
            if (jlRedisson.type().equals(JLRedisson.LOCK)) {
                jlRedissonTemplate.lock(lock, loseTime);
                fal = true;
            } else {
                int waitTime = jlRedisson.waitTime();
                fal = jlRedissonTemplate.tryLock(lock, waitTime, loseTime);
            }
            if (fal) {
                result = joinPoint.proceed(args);
            } else {
                throw new JLRedissonError(jlRedisson.message());
            }
        } catch (Exception e) {
            throw e;
        } finally {
            jlRedissonTemplate.unlock(lock);
        }
        return result;
    }
}
